package com.csw.compose.ui.module.component.custom

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.max
import com.csw.compose.theme.pagePadding
import com.csw.compose.ui.Destination
import com.csw.compose.ui.components.BodyText
import com.csw.compose.ui.components.LabelText
import com.csw.compose.ui.components.LargeSpacer
import com.csw.compose.ui.components.NormalSpacer
import com.csw.compose.ui.components.PrimaryTitle
import com.csw.compose.ui.components.UlItem
import com.csw.compose.ui.module.BasePage
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive

@Preview
@Composable
fun CustomLayoutPagePreview() {
    BasePage({}, "自定义组件-布局") {
        CustomLayoutPage()
    }
}

class CustomLayoutPageData {
    companion object : Destination("CustomLayoutPage")
}

@Composable
fun CustomLayoutPage() {
    Column(
        modifier = Modifier
            .padding(horizontal = pagePadding)
            .verticalScroll(rememberScrollState())
    ) {
        PrimaryTitle("简介")
        BodyText("一个组件在屏幕上呈现需要经过 测量->放置->绘制三个过程，这里主要讲怎么通过Layout组件实现子组件排布")
        NormalSpacer()

        val text = remember { mutableStateOf("333333333333333333333333333") }
        LaunchedEffect(Unit) {
            while (isActive) {
                text.value = StringBuilder().apply {
                    repeat(20 + (Math.random() * 20).toInt()) {
                        append("3")
                    }
                }.toString()
                delay(3000)
            }
        }
        MyColumn(
            Modifier
                .fillMaxWidth()
                .background(Color.Green),
        ) {
            Text(
                "11111111", Modifier.background(Color.Red)
            )
            Text("22222222222222222")
            Text(text.value)
        }
        UlItem("Layout")
        LabelText("布局组件，用于实现自定义布局")
        LabelText("要注意，因为Compose采用单次测量模式来避免因多层嵌套布局的重复测量导致测量次数指数级上涨，但也因此无法在测量之后修改子组件尺寸（除非重组）")

        LargeSpacer()
        EqualWidthColumn(
            Modifier
                .fillMaxWidth()
                .background(Color.Green),
        ) {
            Text(
                "11111111", Modifier.background(Color.Red)
            )
            Text("22222222222222222")
            Text(text.value)
        }
        UlItem("SubcomposeLayout")
        LabelText("子组合布局组件，对比Layout的优势，他允许重复组合子项。")
        LabelText("要注意，subcompose虽然可以重复测量子项，但也会有性能问题，尽量少用。")
    }
}

@Composable
fun MyColumn(
    modifier: Modifier, content: @Composable () -> Unit
) {
    Layout(
        content, modifier
    ) { measurables, constraints ->
        var maxWidth = 0
        var heightSum = 0
        //1、测量
        val placeables = measurables.map { child ->
            //compose 遵循单次测量，Measurable.measure方法只允许执行一次
            //这样可以避免像View那样层层布局进行多次测量导致实际测量次数出现指数级递增
            child.measure(constraints).also {
                if (it.width > maxWidth) {
                    maxWidth = it.width
                }
                heightSum += it.height
            }
        }
        //2、放置
        layout(
            if (constraints.hasFixedWidth) {
                constraints.minWidth
            } else {
                maxWidth
            }, heightSum
        ) {
            var offsetY = 0
            placeables.forEach { child ->
                child.placeRelative(
                    0, offsetY
                )//该方法支持自动转为RTL布局
                offsetY += child.height
            }
        }
    }
}


@Composable
fun EqualWidthColumn(
    modifier: Modifier, content: @Composable () -> Unit
) {
    SubcomposeLayout(
        modifier
    ) { constraints ->
        var maxWidth = 0
        var heightSum = 0
        //1、测量
        //先测量真实内容宽度，计算最大值
        subcompose("realSizeMeasure", content).forEach { child ->
            child.measure(constraints.copy(minWidth = 0)).also {
                if (it.width > maxWidth) {
                    maxWidth = it.width
                }
                heightSum += it.height
            }
        }
        //重组，将所有子组件限制为最大宽度
        val placeables = subcompose("equalWidthMeasure", content).map { child ->
            child.measure(constraints.copy(minWidth = maxWidth, maxWidth = maxWidth))
        }
        //2、放置
        layout(
            if (constraints.hasFixedWidth) {
                constraints.minWidth
            } else {
                maxWidth
            }, heightSum
        ) {
            var offsetY = 0
            placeables.forEach { child ->
                child.placeRelative(
                    0, offsetY
                )//该方法支持自动转为RTL布局
                offsetY += child.height
            }
        }
    }
}



